// ++++++++++++++++++++++++++++++++++++++++
// 《零基础Go语言算法实战》源码
// ++++++++++++++++++++++++++++++++++++++++
// Author:廖显东（ShirDon）
// Blog:https://www.shirdon.com/
// Gitee:https://gitee.com/shirdonl/goAlgorithms.git
// Buy link :https://item.jd.com/14101229.html
// ++++++++++++++++++++++++++++++++++++++++

package main

import (
	"fmt"
	"sync"
)

// 无向图
type undirectedGraph struct {
	nodes []*Node
	edges map[Node][]*Node
	lock  sync.RWMutex
}

// 单个节点
type Node struct {
	Value interface{}
}

func (n *Node) String() string {
	return fmt.Sprintf("%v", n.Value)
}

// 向图中添加一个节点
func (g *undirectedGraph) AddNode(n *Node) {
	g.lock.Lock()
	g.nodes = append(g.nodes, n)
	g.lock.Unlock()
}

// 向图中添加一个边
func (g *undirectedGraph) AddEdge(n1, n2 *Node) {
	g.lock.Lock()
	if g.edges == nil {
		g.edges = make(map[Node][]*Node)
	}
	g.edges[*n1] = append(g.edges[*n1], n2)
	g.edges[*n2] = append(g.edges[*n2], n1)
	g.lock.Unlock()
}

// 打印字符串
func (g *undirectedGraph) String() {
	g.lock.RLock()
	str := ""
	for i := 0; i < len(g.nodes); i++ {
		str += g.nodes[i].String() + " -> "
		near := g.edges[*g.nodes[i]]
		for j := 0; j < len(near); j++ {
			str += near[j].String() + " "
		}
		str += "\n"
	}
	fmt.Println(str)
	g.lock.RUnlock()
}

func main() {
	nodeA := Node{"X"}
	nodeB := Node{"Y"}
	nodeC := Node{"Z"}

	gra := undirectedGraph{}
	gra.AddNode(&nodeA)
	gra.AddNode(&nodeB)
	gra.AddNode(&nodeC)

	gra.AddEdge(&nodeA, &nodeB)
	gra.AddEdge(&nodeA, &nodeC)
	gra.AddEdge(&nodeB, &nodeC)
	gra.String()
}

//$ go run undirectedGraph.go
//X -> Y Z
//Y -> X Z
//Z -> X Y
